/**
 * @description 由一个组件，向上找到最近的指定组件
 * @param context 当前组件，一般为this
 * @param componentName 需要查找的组件名称
 * @returns 返回组件实例
 */

function findComponentUpward(context, componentName) {
  let parent = context.$parent
  let name = parent.$options.name
  // 向上递归查找
  while (parent && (!name || [componentName].indexOf(name) < 0)) {
    parent = parent.$parent
    if (parent) name = parent.$options.name
  }
  return parent
}

/**
 * @description 由一个组件，向上找到所有的指定组件
 * @param context 当前组件，一般为this
 * @param componentName 需要查找的组件名称
 * @returns 返回组件实例集合
 */

function findComponentsUpward(context, componentName) {
  const parents = []
  const parent = context.$parent

  if (parent) {
    if (parent.$options.name === componentName) parents.push(parent)
    return parents.concat(findComponentsUpward(parent, componentName))
  } else {
    return []
  }
}

/**
 * @description 由一个组件向下找到最近的指定组件
 * @param context 当前组件，一般为this
 * @param componentName 需要查找的组件名称
 * @returns 返回组件实例
 */

function findComponentDownward(context, componentName) {
  const childrens = context.$children
  let children = null
  if (childrens.length) {
    // eslint-disable-next-line no-unused-vars
    for (const child of childrens) {
      const name = child.$options.name
      if (name === componentName) {
        children = child
        break
      } else {
        children = findComponentDownward(child, componentName)
        if (children) break
      }
    }
  }
  return children
}

/**
 * @description 向下找到所有指定的组件
 * @param context 当前组件，一般为this
 * @param componentName 需要查找的组件名称
 * @returns 返回组件实例数组集合
 */

function findComponentsDownward(context, componentName) {
  return context.$children.reduce((components, child) => {
    if (child.$options.name === componentName) components.push(child)
    const foundChilds = findComponentsDownward(child, componentName)
    return components.concat(foundChilds)
  }, [])
}

/**
 * @description 找到指定组件的兄弟组件
 * @param context 当前组件，一般为this
 * @param componentName 需要查找的组件名称
 * @param exceptMe 是否除了自身，默认为true
 * @returns 返回组件实例数组集合
 */

function findBrothersComponents(context, componentName, exceptMe = true) {
  const res = context.$parent.$children.filter(item => item.$options.name === componentName)
  const index = res.findIndex(item => item._uid === context._uid)
  exceptMe && res.splice(index, 1)
  return res
}

export {
  findComponentUpward, 
  findComponentsUpward,
  findComponentDownward, 
  findComponentsDownward, 
  findBrothersComponents 
}
